Carousel System

**Referenced Files in This Document** - [carousel-system.js](file://src/assets/js/modules/carousel-system.js) - [main.js](file://src/assets/js/main.js) - [08-carousel-shared-infrastructure.css](file://src/assets/css/modules/08-carousel-shared-infrastructure.css) - [09-services-carousel-homepage.css](file://src/assets/css/modules/09-services-carousel-homepage.css) - [11-testimonials-carousel.css](file://src/assets/css/modules/11-testimonials-carousel.css) - [13-news-carousel-homepage.css](file://src/assets/css/modules/13-news-carousel-homepage.css) - [index.njk](file://src/index.njk) - [capabilities.json](file://src/_data/capabilities.json) - [testimonials.json](file://src/_data/testimonials.json)

Table of Contents

  1. Introduction
  2. Project Structure
  3. Core Components
  4. Architecture Overview
  5. Detailed Component Analysis
  6. Dependency Analysis
  7. Performance Considerations
  8. Troubleshooting Guide
  9. Conclusion
  10. Appendices

Introduction

This document explains the modular carousel system that powers three distinct carousels on the site: capabilities, testimonials, and news. It covers unified configuration, scroll-based navigation, responsive item sizing, auto-generated pagination dots with active state management, keyboard navigation, and accessibility features. It also provides guidance for extending the system and adding new carousel instances.

Project Structure

The carousel system is implemented as a single modular JavaScript module that initializes all supported carousels on DOMContentLoaded. Styles are organized per carousel type with shared infrastructure styles for navigation buttons and pagination dots.

graph TB
JS["carousel-system.js<br/>initCarousels()"] --> DOM["index.njk<br/>HTML markup"]
JS --> CSS1["09-services-carousel-homepage.css"]
JS --> CSS2["11-testimonials-carousel.css"]
JS --> CSS3["13-news-carousel-homepage.css"]
JS --> CSSShared["08-carousel-shared-infrastructure.css"]
DOM --> DataCap["capabilities.json"]
DOM --> DataTesti["testimonials.json"]

Diagram sources

  • [carousel-system.js:3-11](file://src/assets/js/modules/carousel-system.js#L3-L11)
  • [main.js:15-19](file://src/assets/js/main.js#L15-L19)
  • [index.njk:51-74](file://src/index.njk#L51-L74)
  • [index.njk:84-107](file://src/index.njk#L84-L107)
  • [index.njk:123-146](file://src/index.njk#L123-L146)

Section sources

  • [main.js:15-19](file://src/assets/js/main.js#L15-L19)
  • [index.njk:51-74](file://src/index.njk#L51-L74)
  • [index.njk:84-107](file://src/index.njk#L84-L107)
  • [index.njk:123-146](file://src/index.njk#L123-L146)

Core Components

  • Unified initialization: The module exports a single initializer that registers configurations for all supported carousels.
  • Scroll-based navigation: Previous/next buttons and keyboard arrows trigger smooth scroll increments based on responsive item counts.
  • Snap points calculation: The system computes scroll targets per visible page of items and updates pagination dots accordingly.
  • Auto-generated pagination: Dots are dynamically created and toggled for active state during scroll.
  • Accessibility: ARIA roles and labels are applied to the viewport and buttons; keyboard navigation is supported.
  • Touch and mouse drag: Implements a lightweight drag-to-scroll gesture with click prevention after drag.
  • Responsive sizing: Item widths and gaps are measured at runtime to compute items-per-page and scroll amounts.

Section sources

  • [carousel-system.js:3-11](file://src/assets/js/modules/carousel-system.js#L3-L11)
  • [carousel-system.js:28-64](file://src/assets/js/modules/carousel-system.js#L28-L64)
  • [carousel-system.js:66-71](file://src/assets/js/modules/carousel-system.js#L66-L71)
  • [carousel-system.js:73-79](file://src/assets/js/modules/carousel-system.js#L73-L79)
  • [carousel-system.js:81-108](file://src/assets/js/modules/carousel-system.js#L81-L108)
  • [carousel-system.js:121-132](file://src/assets/js/modules/carousel-system.js#L121-L132)
  • [carousel-system.js:134-165](file://src/assets/js/modules/carousel-system.js#L134-L165)

Architecture Overview

The carousel system follows a modular pattern: a single initializer coordinates multiple carousel instances. Each instance encapsulates its own DOM queries, event listeners, and state updates.

sequenceDiagram
participant Doc as "DOM"
participant Main as "main.js"
participant Init as "initCarousels()"
participant Setup as "setupCarousel(cfg)"
participant Viewport as "#<track-id>"
participant BtnPrev as "#<prev-id>"
participant BtnNext as "#<next-id>"
participant Dots as "#<dots-id>"
Doc->>Main : "DOMContentLoaded"
Main->>Init : "initCarousels()"
Init->>Setup : "setupCarousel(config)"
Setup->>Viewport : "query track/items"
Setup->>Dots : "renderDots()"
Setup->>BtnPrev : "add click handler"
Setup->>BtnNext : "add click handler"
Setup->>Viewport : "add scroll/keydown handlers"
Setup->>Viewport : "set ARIA attributes"
Note over Setup,Viewport : "Drag-to-scroll and click prevention"

Diagram sources

  • [main.js:15-19](file://src/assets/js/main.js#L15-L19)
  • [carousel-system.js:3-11](file://src/assets/js/modules/carousel-system.js#L3-L11)
  • [carousel-system.js:13-166](file://src/assets/js/modules/carousel-system.js#L13-L166)

Detailed Component Analysis

Unified Initialization and Configuration

  • The initializer defines a configuration array with identifiers for each carousel’s viewport, previous/next buttons, and pagination container.
  • It iterates over configurations and delegates setup to a shared function that handles DOM queries, rendering, and event binding.

Section sources

  • [carousel-system.js:3-11](file://src/assets/js/modules/carousel-system.js#L3-L11)

Track and Items Resolution

  • The setup function locates the track element inside the viewport or falls back to direct children.
  • It builds an array of items for subsequent calculations and rendering.

Section sources

  • [carousel-system.js:13-22](file://src/assets/js/modules/carousel-system.js#L13-L22)

Pagination Dots Generation and Active State

  • Dots are generated based on computed snap points derived from visible items per page.
  • Each dot is clickable and triggers smooth scroll to the associated snap point.
  • Active dot is determined by proximity to the current scroll offset.
flowchart TD
Start(["Render Dots"]) --> MaxScroll["Compute max scroll"]
MaxScroll --> CheckMax{"maxScroll > 0?"}
CheckMax --> |No| Exit["Exit (no dots)"]
CheckMax --> |Yes| Measure["Measure item width + gap"]
Measure --> ItemsPer["Compute items per page"]
ItemsPer --> Loop["Iterate items by itemsPerPage"]
Loop --> SnapCalc["Compute snap point for group start"]
SnapCalc --> Bounds{"Within max scroll?"}
Bounds --> |Yes| AddSnap["Add snap point"]
Bounds --> |No| FinalSnap["Ensure last snap equals max scroll"]
AddSnap --> Loop
FinalSnap --> Render["Create dot buttons and attach click handlers"]
Render --> Active["On scroll: compute active dot"]
Active --> End(["Done"])

Diagram sources

  • [carousel-system.js:28-64](file://src/assets/js/modules/carousel-system.js#L28-L64)
  • [carousel-system.js:81-108](file://src/assets/js/modules/carousel-system.js#L81-L108)

Section sources

  • [carousel-system.js:28-64](file://src/assets/js/modules/carousel-system.js#L28-L64)
  • [carousel-system.js:81-108](file://src/assets/js/modules/carousel-system.js#L81-L108)

Scroll Amount Calculation and Navigation

  • The scroll amount is calculated as the width of one item plus the gap, multiplied by items per page.
  • Previous/next buttons scroll by this amount with smooth behavior.

Section sources

  • [carousel-system.js:66-71](file://src/assets/js/modules/carousel-system.js#L66-L71)
  • [carousel-system.js:73-79](file://src/assets/js/modules/carousel-system.js#L73-L79)

Keyboard Navigation and ARIA

  • The viewport is focusable and labeled for assistive technologies.
  • Left/right arrow keys trigger smooth scroll increments.
  • Buttons receive ARIA labels for “previous” and “next”.

Section sources

  • [carousel-system.js:121-127](file://src/assets/js/modules/carousel-system.js#L121-L127)
  • [carousel-system.js:129-132](file://src/assets/js/modules/carousel-system.js#L129-L132)

Touch and Mouse Drag Interaction

  • A lightweight drag implementation tracks mouse movement and updates scroll position.
  • Click events are suppressed immediately after a drag to prevent accidental clicks.
  • Visual feedback adjusts cursor and selection during drag.
sequenceDiagram
participant User as "User"
participant Viewport as "Carousel Viewport"
participant Window as "Window"
User->>Viewport : "mousedown"
Viewport->>Viewport : "store start X and scrollLeft"
Window->>Window : "mousemove"
Window->>Viewport : "if dragged : update scrollLeft"
Window->>Window : "mouseup"
Window->>Viewport : "mark wasDragging and reset state"
Viewport->>Viewport : "prevent click if wasDragging"

Diagram sources

  • [carousel-system.js:140-165](file://src/assets/js/modules/carousel-system.js#L140-L165)

Section sources

  • [carousel-system.js:134-165](file://src/assets/js/modules/carousel-system.js#L134-L165)

Styles and Responsive Behavior

  • Shared styles define navigation buttons and pagination dots with consistent appearance and hover/focus states.
  • Per-carousel styles define track layout, scroll snapping, item sizing, and responsive widths.
  • Tracks use scroll-snap-type and overflow-x with hidden scrollbars to rely on pagination dots.

Section sources

  • [08-carousel-shared-infrastructure.css:5-87](file://src/assets/css/modules/08-carousel-shared-infrastructure.css#L5-L87)
  • [09-services-carousel-homepage.css:17-44](file://src/assets/css/modules/09-services-carousel-homepage.css#L17-L44)
  • [11-testimonials-carousel.css:17-43](file://src/assets/css/modules/11-testimonials-carousel.css#L17-L43)
  • [13-news-carousel-homepage.css:16-40](file://src/assets/css/modules/13-news-carousel-homepage.css#L16-L40)

HTML Markup and Content Data

  • The homepage template wires up three carousels with dedicated IDs for viewport, buttons, and pagination containers.
  • Content is populated via data files for capabilities and testimonials.

Section sources

  • [index.njk:51-74](file://src/index.njk#L51-L74)
  • [index.njk:84-107](file://src/index.njk#L84-L107)
  • [index.njk:123-146](file://src/index.njk#L123-L146)
  • [capabilities.json:1-53](file://src/_data/capabilities.json#L1-L53)
  • [testimonials.json:1-24](file://src/_data/testimonials.json#L1-L24)

Dependency Analysis

The carousel system depends on:

  • DOM structure defined in the homepage template.
  • Shared CSS for navigation and pagination.
  • Per-carousel CSS for layout and sizing.
  • Data files for content population.
graph LR
Init["initCarousels()"] --> Setup["setupCarousel(cfg)"]
Setup --> HTML["index.njk markup"]
Setup --> SharedCSS["08-carousel-shared-infrastructure.css"]
Setup --> ServicesCSS["09-services-carousel-homepage.css"]
Setup --> TestimonialsCSS["11-testimonials-carousel.css"]
Setup --> NewsCSS["13-news-carousel-homepage.css"]
HTML --> DataCap["capabilities.json"]
HTML --> DataTesti["testimonials.json"]

Diagram sources

  • [carousel-system.js:3-11](file://src/assets/js/modules/carousel-system.js#L3-L11)
  • [index.njk:51-74](file://src/index.njk#L51-L74)
  • [index.njk:84-107](file://src/index.njk#L84-L107)
  • [index.njk:123-146](file://src/index.njk#L123-L146)
  • [capabilities.json:1-53](file://src/_data/capabilities.json#L1-L53)
  • [testimonials.json:1-24](file://src/_data/testimonials.json#L1-L24)

Section sources

  • [main.js:15-19](file://src/assets/js/main.js#L15-L19)
  • [index.njk:51-74](file://src/index.njk#L51-L74)
  • [index.njk:84-107](file://src/index.njk#L84-L107)
  • [index.njk:123-146](file://src/index.njk#L123-L146)

Performance Considerations

  • Passive event listeners: Scroll and resize handlers are attached with passive: true to avoid blocking the main thread.
  • Debounced resize handling: The implementation listens to resize with a passive listener and recomputes dots and state; consider adding explicit throttling/debouncing for heavy layouts.
  • Memory management: Event listeners are attached once per carousel instance; ensure cleanup if dynamic DOM removal is introduced.
  • Smooth scrolling: Uses native smooth behavior for efficient animation.
  • Drag performance: Lightweight mousemove tracking avoids heavy computations; ensure minimal DOM reads during drag.

Section sources

  • [carousel-system.js:110-114](file://src/assets/js/modules/carousel-system.js#L110-L114)
  • [carousel-system.js:148-153](file://src/assets/js/modules/carousel-system.js#L148-L153)

Troubleshooting Guide

  • Carousels not initializing:
    • Verify IDs for viewport, prev/next buttons, and pagination containers match the configuration.
    • Confirm the initializer runs after DOMContentLoaded.
  • No pagination dots:
    • Ensure the viewport has content and measurable width; the renderer exits early if max scroll is zero.
    • Check that the dots container exists and is accessible.
  • Navigation disabled:
    • If the viewport cannot scroll horizontally, previous/next buttons become disabled; verify content and widths.
  • Keyboard navigation not working:
    • Confirm the viewport is focusable and reachable via tab order.
  • Drag conflicts:
    • Click suppression occurs only for immediate post-drag; ensure no other click handlers interfere.

Section sources

  • [carousel-system.js:13-22](file://src/assets/js/modules/carousel-system.js#L13-L22)
  • [carousel-system.js:28-35](file://src/assets/js/modules/carousel-system.js#L28-L35)
  • [carousel-system.js:81-89](file://src/assets/js/modules/carousel-system.js#L81-L89)
  • [carousel-system.js:121-127](file://src/assets/js/modules/carousel-system.js#L121-L127)
  • [carousel-system.js:163-165](file://src/assets/js/modules/carousel-system.js#L163-L165)

Conclusion

The carousel system provides a unified, accessible, and responsive solution for capabilities, testimonials, and news carousels. Its modular design simplifies extension to new carousels, while shared styles and consistent interaction patterns ensure a cohesive user experience.

Appendices

Practical Examples

  • Initializing all carousels:

    • Call the exported initializer after DOM is ready.
    • See [main.js:15-19](file://src/assets/js/main.js#L15-L19).
  • Adding a new carousel instance:

    • Define IDs for the viewport, prev/next buttons, and pagination container in the template.
    • Extend the configuration array with the new carousel identifiers.
    • Reference [carousel-system.js:3-11](file://src/assets/js/modules/carousel-system.js#L3-L11).
  • Customizing responsive breakpoints:

    • Adjust per-carousel CSS widths and gaps to change items-per-page.
    • See [09-services-carousel-homepage.css:46-48](file://src/assets/css/modules/09-services-carousel-homepage.css#L46-L48), [11-testimonials-carousel.css:30-33](file://src/assets/css/modules/11-testimonials-carousel.css#L30-L33), [13-news-carousel-homepage.css:29-32](file://src/assets/css/modules/13-news-carousel-homepage.css#L29-L32).
  • Accessibility checklist:

    • Ensure ARIA labels for buttons and viewport are present.
    • Confirm keyboard arrow navigation and focus order.
    • Reference [carousel-system.js:121-132](file://src/assets/js/modules/carousel-system.js#L121-L132).